﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Configuration;
using System.Web.Management;
using System.Web.Security;
using MVCms.Core.DataAccess;
using MVCms.Core.Entities;
using MVCms.Core.Models;
using System.Data.SqlClient;
using System.IO;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Configuration = System.Configuration.Configuration;


namespace MVCms.Core.Services
{
    /// <summary>
    /// Setup Service
    /// </summary>
    public class SetupService
    {
        public static SystemSetupModel setupModel;
        /// <summary>
        /// Starts the system setup.
        /// </summary>
        /// <param name="systemSetupModel">The system setup model.</param>
        public static void Start(SystemSetupModel systemSetupModel)
        {
            ExecuteScripts();
            setupModel = systemSetupModel;
            CreatePage("Home", null);
            var account = CreatePage("Account", null); 
            var admin = CreatePage("Admin", null);

            List<VirtualPage> pages = new List<VirtualPage>
                                          {
                                              CreatePage("PageManager", admin),
                                              CreatePage("ManageUsers", admin),
                                              CreatePage("Authentication", admin),
                                              CreatePage("Create", account),
                                              CreatePage("Login", account),
                                          };


            AddModules();
            AssignDefaultModules(pages);
            CreateMembershipSchema();
            InsertDefaultMembershipData();
            UpadateConfig();


        }

        /// <summary>
        /// Inserts the default membership data.
        /// </summary>
        private static void InsertDefaultMembershipData()
        {
            Roles.CreateRole("Administrator");
            MembershipUser user = Membership.CreateUser(setupModel.AdminUsername, setupModel.AdminPassword, setupModel.AdminEmail);
            Roles.AddUsersToRole(new string[] { setupModel.AdminUsername }, "Administrator");

            foreach (VirtualPage page in PageService.GetPages().Where(p=> (p.Parent != null && p.Parent.Name == "Admin") || p.Name == "Admin"))
            {
                new PageRole
                    {
                        Role = "Administrator",
                        VirtualPage = page
                    }.Save();
            }

            FormsAuthentication.SetAuthCookie(user.UserName, false);
        }

        /// <summary>
        /// Upadates the config to stop setup from running again.
        /// </summary>
        private static void UpadateConfig()
        {
            Configuration configFile = WebConfigurationManager.OpenWebConfiguration("~");
            AppSettingsSection AppSection = configFile.GetSection("appSettings") as AppSettingsSection;
            AppSection.Settings["RunMigrations"].Value = "false";
            configFile.Save();
        }

        /// <summary>
        /// Assigns the default modules.
        /// </summary>
        /// <param name="pages">The pages.</param>
        private static void AssignDefaultModules(List<VirtualPage> pages)
        {
            foreach (VirtualPage virtualPage in pages)
            {
                switch (virtualPage.Name)
                {
                    case "PageManager":
                        foreach (PluginModule pluginModule in PluginService.GetModules().Where(pm 
                            => pm.Plugin.Name == "Plugin.Admin.Controlbox.dll"
                            || pm.Plugin.Name == "Plugin.Admin.PageManager.dll"
                            || pm.Plugin.Name == "Plugin.Admin.UploadModule.dll"
                            || pm.Plugin.Name == "Plugin.Admin.PageManager.dll"
                            || pm.Plugin.Name == "Plugin.Admin.PageManager.dll"))
                        {
                            new PageModule
                                {
                                    Title = pluginModule.Name,
                                    Module = pluginModule,
                                    Panel = "0",
                                    Position = 0,
                                    VirtualPage = virtualPage
                                    
                                }.Save();
                        }
                        break;
                    case "ManageUsers":
                        foreach (PluginModule pluginModule in PluginService.GetModules().Where(pm => pm.Plugin.Name == "Plugin.Admin.UserAdministration.dll"))
                        {
                            new PageModule
                            {
                                Title = pluginModule.Name,
                                Module = pluginModule,
                                Panel = "0",
                                Position = 0,
                                VirtualPage = virtualPage
                            }.Save();
                        }
                        break;
                    case "Authentication":
                        foreach (PluginModule pluginModule in PluginService.GetModules().Where(pm => pm.Plugin.Name == "Plugin.UserFormsAuthentication.dll"))
                        {
                            new PageModule
                            {
                                Title = pluginModule.Name,
                                Module = pluginModule,
                                Panel = "0",
                                Position = 0,
                                VirtualPage = virtualPage
                            }.Save();
                        }
                        break;
                    case "Create":
                        foreach (PluginModule pluginModule in PluginService.GetModules().Where(pm => pm.Controller == "Account" && pm.Action == "Register"))
                        {
                            new PageModule
                            {
                                Title = pluginModule.Name,
                                Module = pluginModule,
                                Panel = "0",
                                Position = 0,
                                VirtualPage = virtualPage
                            }.Save();
                        }
                        break;
                    case "Login":
                        foreach (PluginModule pluginModule in PluginService.GetModules().Where(pm => pm.Controller == "Account" && pm.Action == "LogOn"))
                        {
                            new PageModule
                            {
                                Title = pluginModule.Name,
                                Module = pluginModule,
                                Panel = "0",
                                Position = 0,
                                VirtualPage = virtualPage
                            }.Save();
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// Adds the modules.
        /// </summary>
        private static void AddModules()
        {
             var directoryInfo = new DirectoryInfo(HttpRuntime.BinDirectory);

             foreach (var fileInfo in directoryInfo.GetFiles())
             {
                 if (!fileInfo.Name.StartsWith("Plugin"))
                 {
                     continue;
                 }
                 if (!fileInfo.Name.EndsWith(".dll"))
                 {
                     continue;
                 }
                 Plugin plugin = new Plugin();

                 plugin.Name = Path.GetFileName(fileInfo.Name);
                 plugin.PluginModules = PluginService.GetPluginModules(plugin, fileInfo);
                 plugin.Save();
             }
        }

        /// <summary>
        /// Creates a page.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="parent">The parent.</param>
        /// <returns></returns>
        private static VirtualPage CreatePage(string name, VirtualPage parent)
        {
            try
            {
                new VirtualPage
                {
                    Name = name,
                    Status = Status.Active,
                    Modules = null,
                    Parent = parent,
                    Title = name,
                }.Save();

                return McContext.Load<VirtualPage>().Where(p => p.Name == name).FirstOrDefault();
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Creates the membership schema.
        /// </summary>
        private static void CreateMembershipSchema()
        {

            
        }

        private static void ExecuteScripts()
        {

            var databaseName = "MVCms";
            var connectionString = ConfigurationManager.ConnectionStrings["MVCms"].ConnectionString;

            SqlServices.Install(databaseName, SqlFeatures.Membership, connectionString);
            SqlServices.Install(databaseName, SqlFeatures.All, connectionString);

            string sqlConnectionString = connectionString;
            FileInfo file = new FileInfo(HttpRuntime.AppDomainAppPath + @"\SetupScripts\ElmahSetup.sql");
            string script = file.OpenText().ReadToEnd();
            SqlConnection conn = new SqlConnection(sqlConnectionString);
            Server server = new Server(new ServerConnection(conn));
            server.ConnectionContext.ExecuteNonQuery(script);
        }

    }
}
